package com.lfy.commons.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.CodeSignature;
import org.springframework.core.env.Environment;
import org.springframework.core.env.Profiles;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@Aspect
public class AspectLog {
    /**
     * 当前环境
     */
    private final Environment env;

    public AspectLog(Environment environment) {
        this.env = environment;
    }

    /**
     * spring框架切入点
     */
    @Pointcut("@within(org.springframework.stereotype.Repository)" +
            "|| @within(org.springframework.stereotype.Service)" +
            "|| @within(org.springframework.web.bind.annotation.RestController)")
    public void springBeanPointcut() {

    }

    /**
     * 项目切入点
     *
     * @param
     * @return
     */
//    @Pointcut("within(com.lfy.*.controller..*)" +
//            "||within(com.lfy.*.service..*)"
//    )
    @Pointcut("within(com.lfy.*.service..*)")
    public void applicationPackagePointcut() {

    }

    @Around(" springBeanPointcut() & applicationPackagePointcut()")
    public Object log(ProceedingJoinPoint joinPoint) throws Throwable {
        Object proceed = null;
        try {
            log.info("进入:{}.{}(),入参[k]:{},入参[v]:{},", joinPoint.getSignature().getDeclaringType(), joinPoint.getSignature().getName(), ((CodeSignature) joinPoint.getSignature()).getParameterNames(), joinPoint.getArgs());
            proceed = joinPoint.proceed();
            log.info("退出:{}.{}(),结果:{}", joinPoint.getSignature().getDeclaringType(), joinPoint.getSignature().getName(), proceed);


        } catch (IllegalAccessError e) {
            log.error("IllegalAccessError:{}.{}(),入参[s]:{},e:{}", joinPoint.getSignature().getDeclaringType(), joinPoint.getSignature().getName(), joinPoint.getArgs(), e);
            throw e;
        }
        return proceed;
    }

    @AfterThrowing(pointcut = "springBeanPointcut() ", throwing = "e")
    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {

        //判断运行环境
        if (env.acceptsProfiles(Profiles.of("dev", "test"))) {
            log.error("错误方法：{}.{}()，cause:{},exception:{}", joinPoint.getSignature().getDeclaringType(), joinPoint.getSignature().getName(),
                    e.getCause() != null ? e.getCause() : "Null",
                    e.getMessage() != null ? e.getMessage() : "Null");
        } else {
            log.error("错误方法：{}.{}()，cause:{},time:{}", joinPoint.getSignature().getDeclaringType(),
                    joinPoint.getSignature().getName(), e.getCause() != null ? e.getCause() : "Null",
                    LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        }

    }
}
